package com.ck.common.utils.http;

import com.ck.common.bean.ReturnResult;
import com.ck.common.utils.txt.TextUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author ck
 */
@Slf4j
@Component
public class OkHttpUtil{

    @Resource
    private OkHttpClient client;
    private long startTime = System.currentTimeMillis();
    private long endTime = System.currentTimeMillis();

    /**
     * POST请求
     *
     * @param reqUrl
     * @param bodyJson
     * @param reqHead
     * @return
     */
    public ReturnResult doPost(String reqUrl, String bodyJson, HashMap<String, String> reqHead) {
        return doPost(reqUrl, bodyJson, reqHead, "application/json");
    }

    /**
     * POST请求
     *
     * @param reqUrl
     * @param bodyJson
     * @param reqHead
     * @return
     */
    public ReturnResult doPost(String reqUrl, String bodyJson, HashMap<String, String> reqHead, String contentType) {
         startTime = System.currentTimeMillis();
        if (StringUtils.isEmpty(contentType)) {
            contentType = "application/json";
        }

//        bodyJson = StringUtils.trimToEmpty(bodyJson);
//        if (StringUtils.isEmpty(bodyJson) && contentType.contains(ProjConstant.CHAR_JSON)) {
//            bodyJson = "{}";
//        }
        ReturnResult result = ReturnResult.fail("请求失败");

        try {
            MediaType jsonType = MediaType.parse(contentType);
            RequestBody body = RequestBody.create(jsonType, bodyJson);
            Request.Builder reqBuilder = new Request.Builder();
            if (reqHead != null) {
                addHeader(reqHead, reqBuilder);
            }
            // 构造请求
            Request request = reqBuilder.url(reqUrl).post(body).build();
            // 发起请求
            result = execute(request);
        } catch (Exception e) {
            log.info("OKHTTP-POST[" + reqUrl + "],BODY:[" + bodyJson.replaceAll("\r|\n", "") + "]请求异常: " + TextUtil.ex2Txt(e));
            result = ReturnResult.fail("请求异常:" + e.getMessage());
        }
        // 计算耗时
        endTime = System.currentTimeMillis();
        log.info("OKHTTP-POST[" + reqUrl + "],BODY:[" + bodyJson.replaceAll("\r|\n", "") + "]请求耗时:" + (endTime - startTime) / 1000.0 + "秒");

        return result;
    }

    /**
     * Get请求
     *
     * @param reqUrl
     * @param reqHead
     * @param map
     * @return
     */
    public ReturnResult doGet(String reqUrl, HashMap<String, String> reqHead, Map<String,String> map) {
        startTime = System.currentTimeMillis();
        Request.Builder reqBuilder = new Request.Builder();
        if (reqHead != null) {
            addHeader(reqHead, reqBuilder);
        }
        ReturnResult result = ReturnResult.fail("请求失败");

        try {
            //拼接url Get请求参数
            String url = getBizUrl(reqUrl, map);
            Request request = reqBuilder.url(url).get().build();
            result = execute(request);
        } catch (Exception e) {
            log.info("OKHTTP-GET[" + reqUrl + "]请求异常:" + TextUtil.ex2Txt(e));
            result = ReturnResult.fail("请求异常:" + e.getMessage());
        }
        // 计算耗时
        endTime = System.currentTimeMillis();
        log.info("OKHTTP-GET[" + reqUrl + "]请求耗时:" + (endTime - startTime) / 1000.0 + "秒");

        return result;
    }

    /**
     * 表单提交
     *
     * @param reqUrl
     * @param bodyMap
     * @param reqHead
     * @return
     */
    public ReturnResult doFormPost(String reqUrl, Map<String, String> bodyMap, HashMap<String, String> reqHead) {
        startTime = System.currentTimeMillis();

        ReturnResult result = ReturnResult.fail("请求失败");

        try {
            FormBody.Builder builder = new FormBody.Builder();
            for (Map.Entry<String, String> entry : bodyMap.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
            Request.Builder reqBuilder = new Request.Builder();
            if (reqHead != null) {
                addHeader(reqHead, reqBuilder);
            }
            // 构造请求
            Request request = reqBuilder.url(reqUrl).post(builder.build()).build();
            // 发起请求
            result = execute(request);
        } catch (Exception e) {
            log.info("OKHTTP-POST[" + reqUrl + "]请求异常:" + TextUtil.ex2Txt(e));
            result = ReturnResult.fail("请求异常: " + e.getMessage());
        }
        // 计算耗时
        endTime = System.currentTimeMillis();
        log.info("OKHTTP-POST[" + reqUrl + "]请求耗时:" + (endTime - startTime) / 1000.0 + "秒");

        return result;
    }

    /**
     * 添加请求头信息
     *
     * @param reqHead
     * @param reqBuilder
     */
    private void addHeader(HashMap<String, String> reqHead, Request.Builder reqBuilder) {
        Iterator<Map.Entry<String, String>> it = reqHead.entrySet().iterator();

        for (Map.Entry<String, String> entry : reqHead.entrySet()) {
            log.info(String.format("addHeader key: %s, value: %s", entry.getKey(), entry.getValue()));
            reqBuilder.addHeader(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 同步执行请求操作
     *
     * @param request
     * @return
     */
    private ReturnResult execute(Request request) throws Exception {
        ReturnResult back = ReturnResult.fail("请求失败");
        Response response;
        response = client.newCall(request).execute();

        String httpCode = String.valueOf(response.code());
        log.info("req[" + request.url().toString() + "].response code:" + httpCode);
        // 封装结果
        if (response.isSuccessful()) {
            String result = response.body() != null ? StringUtils.trimToEmpty(response.body().string()).replaceAll("\r|\n", "") : "";
            log.info("response result:" + result);
            back = ReturnResult.success(result);
        } else {
            String msg = httpCode;
            if (response.body() != null && response.body().contentLength() > 0L) {
                msg = StringUtils.trimToEmpty(response.body().string()).replaceAll("\r|\n", "");
            }

            back = new ReturnResult(httpCode, msg, null);
        }
        return back;
    }

    /**
     * 拼接Get请求的 URL
     * @param serverAddress
     * @param reqParams
     * @return
     */
    private String getBizUrl(String serverAddress, Map<String, String> reqParams) {
        String inputChar = "utf-8";
        StringBuffer parameter = new StringBuffer("");
        parameter.append(serverAddress).append("?");
        List<String> keys = new ArrayList<>(reqParams.keySet());
        for (int i = 0; i < keys.size(); i++) {
            try {
                parameter.append(keys.get(i)).append("=").append(URLEncoder.encode((String) reqParams.get(keys.get(i)), inputChar)).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return parameter.toString();
    }

}
